import path from 'path';
import router from 'koa-router';
import DBTool from '../com/DBTool/DBTool';
import configTool from '../com/configTool';
import koaBody from 'koa-body';
import DBConnectTool from '../com/DBTool/DBConnectTool';
import threadEncryptFiles from '../lib/FSTool/EncryptFiles/threadEncryptFiles/index';
import webSocketTool from '../com/webSocketTool/webSocketTool';
import getFilePathList from '../lib/FSTool/getFilePathList';
import LogTool from '../com/LogTool/LogTool';

const ManageRoutes = new router({prefix: '/manage'});


ManageRoutes
    .get('/getDBInfoList', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let fileInfoList = await DBTool.getDBInfoList() || [];
        const normalDBExt = configTool.baseConfig.normalDBExt;
        const encryptDBExt = configTool.baseConfig.encryptDBExt;

        // 构造正则表达式字符串，使用变量值
        const regexStr = `-MD5-..?\\.(${normalDBExt}|${encryptDBExt})$`;

        // 创建正则表达式对象
        const regex = new RegExp(regexStr);

        fileInfoList = fileInfoList.filter(item => !(regex.test(item.filePath)));

        ctx.body = JSON.stringify(fileInfoList);
    })
    .get('/getDBPathTree', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let {DBName} = ctx.request.query;
        let dbTool = await DBConnectTool.openDB(DBName);
        let res = await dbTool.getDBPathTree();
        ctx.body = JSON.stringify(res);
    })
    .get('/getFileListByPath', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let {DBName, path} = ctx.request.query;
        let dbTool = await DBConnectTool.openDB(DBName);
        let res = await dbTool.getDirListByPath(path);
        ctx.body = JSON.stringify(res);
    })
    .get('/getDirInfo', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let {DBName, dirPath} = ctx.request.query;
        let dbTool = await DBConnectTool.openDB(DBName);
        let res = await dbTool.getDirInfo(dirPath);
        ctx.body = JSON.stringify(res);
    })
    /* 原有路由 … */
    .post('/uploadDB', koaBody({
            multipart: true,
            formLimit: '2000mb',
            jsonLimit: '20mb',
            formidable: {
                keepExtensions: true, // 保留文件扩展名
                maxFileSize: 8 * 1024 * 1024 * 1024,
                filename: (name, ext, part) => {
                    // 自定义文件名：原文件名 + 时间戳
                    return `${part.originalFilename?.replace(/[\/\\]/g, '_')}_${Date.now()}${ext}`;
                },
                onFileBegin(name, file: any) {
                    // 自定义文件保存路径
                    const upload_dir = path.join(configTool.appBasePath, '/temp/fileDB/upload');
                    file.filepath = path.join(upload_dir, file.originalFilename);
                }
            }
        }), async (ctx) => {
            const file = ctx.request.files?.file as any;
            if (!file) {
                ctx.status = 400;
                ctx.body = {ok: false, message: '缺少 file 字段'};
                return;
            }
            // formidable 已自动移动到 UPLOAD_DIR
            ctx.set('content-type', 'application/json;charset=utf-8');
            ctx.body = JSON.stringify({
                ok: true,
                filePath: file.filepath,
                fileName: path.basename(file.filepath),
                size: file.size
            });
        }
    )
    .get('/createDB', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let {DBName, targetDirectory, mataData} = ctx.request.query;
        if (mataData) {
            mataData = JSON.parse(mataData);
        }
        let msg = await DBTool.createDB(DBName, targetDirectory, mataData);
        ctx.body = JSON.stringify({msg});
    })
    .get('/appendFile', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let {DBName, targetDirectory, currentDirectory} = ctx.request.query;
        let msg = await DBTool.appendFile(DBName, targetDirectory, currentDirectory);
        await DBConnectTool.reConnect(DBName);
        ctx.body = JSON.stringify({msg});
    })
    .get('/clearFileDate', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let {DBName} = ctx.request.query;
        let dbTool = await DBConnectTool.openDB(DBName);
        await DBConnectTool.reConnect(DBName);
        let res = await dbTool.clearFileDate();
        ctx.body = JSON.stringify(res);
    })
    .get('/wipeCache', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let {DBName} = ctx.request.query;
        let dbTool = await DBConnectTool.openDB(DBName);
        await DBConnectTool.reConnect(DBName);
        let res = await dbTool.wipeCache();
        ctx.body = JSON.stringify(res);
    })
    .get('/deleteByFullPath', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let {DBName, fullPath} = ctx.request.query;
        let dbTool = await DBConnectTool.openDB(DBName);
        await DBConnectTool.reConnect(DBName);
        let res = await dbTool.deleteByFullPath(fullPath);
        ctx.body = JSON.stringify(res);
    })
    .get('/deleteByDir', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let {DBName, directory} = ctx.request.query;
        let dbTool = await DBConnectTool.openDB(DBName);
        await DBConnectTool.reConnect(DBName);
        let res = await dbTool.deleteByDir(directory);
        ctx.body = JSON.stringify(res);
    })
    .get('/exportDB', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let {DBName, targetDirectory} = ctx.request.query;
        let res = await DBTool.exportDB(DBName, targetDirectory);
        ctx.body = JSON.stringify({res});
    })
    .get('/deleteDB', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let {DBName} = ctx.request.query;
        if (DBName) {
            await DBConnectTool.closeAll();
            let result = await DBTool.deleteDB(DBName);
            ctx.body = JSON.stringify({result});
        } else {
            ctx.status = 404;
        }
    })
    .get('/getFileBySearch', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let {DBName, text} = ctx.request.query;
        if (DBName && text) {
            let dbTool = await DBConnectTool.openDB(DBName);
            let list = await dbTool.getFileListBySearch(text);
            list.map((item: any) => item.ext = path.extname(item.file_name));
            ctx.body = JSON.stringify(list);
        } else {
            ctx.status = 404;
        }
    })


    .get('/getMataData', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let {DBName} = ctx.request.query;
        if (DBName) {
            let dbTool = await DBConnectTool.openDB(DBName);
            ctx.body = await dbTool.getMataData();
        } else {
            ctx.status = 404;
        }
    })
    .get('/threadEncryptFiles', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let {inputPath, outPutPath, passWorld, threadNum} = ctx.request.query;
        if (inputPath && outPutPath && passWorld && threadNum) {
            const filePathList = await getFilePathList(inputPath);

            const beginTime = new Date().getTime();
            const mes = await threadEncryptFiles(filePathList, inputPath, outPutPath, passWorld, (e: any) => {
                e.action = 'runProgress';
                e.passTime = Math.ceil((new Date().getTime() - beginTime) / 1000);
                webSocketTool.sendToAllUser(JSON.stringify(e));
            }, threadNum);

            ctx.body = JSON.stringify(mes);
        } else {
            ctx.status = 400;
            ctx.body = JSON.stringify({message: '参数错误'});
        }
    })

    .get('/getClientServerWebLog', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        ctx.status = 200;
        const logList = await LogTool.queryLog('info');
        ctx.body = logList
            .filter((item: any) => item.message.startsWith('http '))
            .map((item: any) => JSON.parse(item.message.replace('http ', '')));
    })
    .get('/getManageServerWebLog', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        ctx.status = 200;
        const logList = await LogTool.queryLog('warn');
        ctx.body = logList
            .filter((item: any) => item.message.startsWith('http '))
            .map((item: any) => JSON.parse(item.message.replace('http ', '')));
    })

    .get('/getLogSummary', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');


        const logSummaryMap = new Map<string, any>();

        let logList = await LogTool.queryLog('info');

        logList = logList.filter((item: any) => item.message.startsWith('http client '))
            .map((item: any) => JSON.parse(item.message.replace('http client ', '')));

        logList.forEach((item: any) => {
            const ip = item.ip;
            const start = new Date(item.start).toDateString();
            const key = `${ip}-${start}`;
            if (logSummaryMap.has(key)) {
                const value = logSummaryMap.get(key);
                value.count++;
            } else {
                const isoDate = new Date(start).toISOString().replace(/T.*/, '');
                logSummaryMap.set(key, {ip, isoDate, count: 1});
            }
        });

        ctx.body = Array.from(logSummaryMap.values());

    })
    .post('/setMataData', async (ctx: any) => {
        ctx.set('content-type', 'application/json;charset=utf-8');
        let {DBName, mataData} = ctx.request.body;
        let dbTool = await DBConnectTool.openDB(DBName);
        if (mataData) {
            mataData = JSON.parse(mataData);
        }
        let msg = await dbTool.addItemToMataData(mataData);
        ctx.body = JSON.stringify({msg});
    });

export default ManageRoutes;
